/*
 *  Disc Catalog
 *  A little application to quickly catalog and find contents of your
 *  DVD archives.
 *
 *  Document.m
 *  The main class for the Document-based Cocoa architecture. This is
 *  also the controller for the documents' main window.
 *
 *  Created by Nicola Gigante on 21/12/08.
 *  Copyright (C) 2008  Nicola Gigante
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#import "Document.h"
#import "IconTextCell.h"

@implementation Document

@synthesize catalog, treeController, scanSheet, scannedDiscs, searchManager, searchField;

+ (NSOperationQueue *)sharedOperationQueue
{
	static NSOperationQueue *queue = nil;
	
	if(queue == nil)
		queue = [[NSOperationQueue alloc] init];
	
	return queue;
}

- (id) init
{
	self = [super init];
	
	self.catalog = [[Catalog alloc] init];
	self.searchManager = [[SearchManager alloc] init];
	lastLabelWasCustom = NO;
	
	return self;
}

- (NSString *)windowNibName
{
    return @"Document";
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
	return [NSKeyedArchiver archivedDataWithRootObject:self.catalog];
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
	self.catalog = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    return YES;
}

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
	if([cell isKindOfClass:[IconTextCell class]])
		[(IconTextCell *)cell setImage: [[item representedObject] icon]];
}

- (void) refilter:(id)sender
{
	self.searchManager.keyword = self.searchField.stringValue;
	if(![self.searchManager.keyword length])
	{
		[treeController setContent:catalog.discs];
	}
	else
	{
		[treeController setContent:[self.searchManager filterDiscs:catalog.discs]];
		[treeController rearrangeObjects];
		[outline expandItem:nil expandChildren:YES];
	}
}

- (void) beginImportCatalog: (id)sender
{
    NSArray *fileTypes = [NSArray arrayWithObject:@"dcat"];
    NSOpenPanel *panel = [NSOpenPanel openPanel];
	
    [panel setRequiredFileType:@"dcat"];
	
	[panel beginSheetForDirectory:NSHomeDirectory() file:nil types:fileTypes modalForWindow:[self windowForSheet] modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}

- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode  contextInfo:(void  *)contextInfo
{
	if(returnCode == NSOKButton)
	{
		Catalog *newCatalog = [NSKeyedUnarchiver unarchiveObjectWithFile:[panel filename]];
		for(Disc *disc in newCatalog.discs)
			[self.catalog insertObject:disc inDiscsAtIndex:[self.catalog countOfDiscs]];
		[self updateChangeCount:NSChangeDone];
	}
}
	
- (void) addDisc: (id)sender
{
	if(!scanSheet)
		[NSBundle loadNibNamed: @"ScanSheet" owner: self];
	
    [NSApp beginSheet: scanSheet
	   modalForWindow: [self windowForSheet]
		modalDelegate: self
	   didEndSelector: @selector(didEndScanSheet:returnCode:contextInfo:)
		  contextInfo: nil];
}

- (void) discInserted:(NSNotification *)notif
{
	NSString *path = [[notif userInfo] objectForKey:@"NSDevicePath"];
	NSString *discName = [[NSFileManager defaultManager] displayNameAtPath:path];
	statusLabel.stringValue = [NSString stringWithFormat:@"Scanning the disc: %@", discName];
	[scanButton setEnabled: NO];
	[closeButton setEnabled: NO];
	[scanSheet.contentView display];
	
	NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(scan:) object:path];
	[op addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:(void *)CFRetain([notif userInfo])];
	
	[[Document sharedOperationQueue] addOperation:op];
}

- (Disc *)scan:(NSString *)path
{
	return [Disc scanFromPath:path];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
	NSInvocationOperation *op = (NSInvocationOperation *)object;
	NSDictionary *userInfo = (NSDictionary *)context;
	NSString *path = [userInfo objectForKey:@"NSDevicePath"];
	NSString *discName = [[NSFileManager defaultManager] displayNameAtPath:path];
	CFRelease(userInfo);
	
	Disc *disc = [op result];
	
	[catalog insertObject:disc inDiscsAtIndex:[catalog countOfDiscs]];
	
	if(self.catalog.labelsEnabled)
	{
		if(!lastLabelWasCustom)
			[catalog.labelManager generateLabel];
		lastLabelWasCustom = NO;
		disc.label = [catalog.labelManager generatedLabel];
		
		[labelLabel setHidden:NO];
		[labelLabel setStringValue:@"Suggested label:"];
		[labelButton setHidden:NO];
		[labelButton setTitle:disc.label];
	}
	
	statusLabel.stringValue = @"Ejecting the disc...";
	[scanSheet.contentView display];
	[[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath:path];
	
	statusLabel.stringValue = [NSString stringWithFormat:@"Added disc: %@", discName];
	[scanButton setEnabled: YES];
	[closeButton setEnabled: YES];
	self.scannedDiscs++;
	[self updateChangeCount:NSChangeDone];
}

- (void) askCustomLabel: (id)sender
{
	[labelButton setHidden: YES];
	[customLabelField setHidden: NO];
	customLabelField.stringValue = self.catalog.lastDisc.label;
}

- (void) customLabelFieldEdited: (id)sender
{
	Disc *lastDisc = self.catalog.lastDisc;
	if(![lastDisc.label isEqual:customLabelField.stringValue])
	{
		self.catalog.lastDisc.label = customLabelField.stringValue;
		labelButton.title = customLabelField.stringValue;
		labelLabel.stringValue = @"Custom label:";
		lastLabelWasCustom = YES;
	}
	[customLabelField setHidden:YES];
	[labelButton setHidden:NO];
}

- (void) startScanning:(id)sender
{
	[readyLabel setHidden: YES];
	[box setHidden: NO];
	[indicator setUsesThreadedAnimation:YES];
	[indicator startAnimation:self];
	[scanButton setTitle:@"Stop scanning..."];
	[scanButton setAction:@selector(stopScanning:)];
	
	[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(discInserted:) name:NSWorkspaceDidMountNotification object:nil];
	
}

- (void) stopScanning: (id)sender
{
	[readyLabel setHidden: NO];
	[box setHidden: YES];
	labelLabel.stringValue = @"Suggested label:";
	[labelLabel setHidden:YES];
	[labelButton setHidden:YES];
	[indicator stopAnimation:self];
	statusLabel.stringValue = @"I'm waiting for a disc...";
	[scanButton setTitle:@"Start scanning..."];
	[scanButton setAction:@selector(startScanning:)];
	
	[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
}

- (void) closeScanSheet:(id)sender
{
	[NSApp endSheet:scanSheet];
}

- (void)didEndScanSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
    [scanSheet orderOut:self];
	[self stopScanning:self];
	self.scannedDiscs = 0;
}

@end
